#import <objc/Object.h>
#import <remote/NXConnection.h>
#import <remote/NXProxy.h>
#import <mach/cthreads.h>
#import <machkit/NXPort.h>

/*
 * A simple, multi-threaded example.
 * Each new client gets a dedicated thread.
 */

@protocol ServerProtocol
- newThread;
- (int) doWork;
@end

@interface MTS : Object <ServerProtocol,NXSenderIsInvalid>
@end

@implementation MTS
// when a new client shows up, build a private connection to it
- connection: (NXConnection *)oldConn didConnect:(NXConnection *)newConn {
	id	outPort = [newConn outPort];
	NXProxy *bogus = [NXConnection connectToPort:outPort];
	NXConnection *newnewConn = [bogus connectionForProxy];

	[newConn free];	// don't need new connection on old inPort
	[newnewConn runInNewThread];	// service new things in new thread
	[newnewConn setRoot:self];	// give new conn a root to serve!
	[newnewConn registerForInvalidationNotification:self];
	return newnewConn;	// service this first request in main thread
}
- newThread {
	return self;	// this will point to newnewConn (and new thread)
}
- (int) doWork {
	return (int) cthread_self();
}

- senderIsInvalid:sender {
	[sender free];
	return self;
}
@end

main() {
	MTS *mts;
	NXConnection *server;
	id proxy1, proxy2;

//	[NXConnection debug:"MTS "];
	mts = [MTS new];
	server = [NXConnection registerRoot:mts withName:"MTS example"];
	if (server) {	// we're it!
		// start up a new thread that will deliver client death notifications
		[NXPort worryAboutPortInvalidation];

		// tell initial connection to tell us about new incoming connections
		[server setDelegate:mts];

		// serve requests
		[server run];
	}
	else {
		[mts free];
		proxy1 = [NXConnection connectToName:"MTS example"];

		if (!proxy1) {
			printf("couldn't get to server\n");
			exit(1);
		}
		[proxy1 setProtocolForProxy:@protocol(ServerProtocol)];

		proxy2 = [proxy1 newThread];
		if (!proxy2) {
			printf("couldn't get new thread\n");
			exit(2);
		}
		[proxy2 setProtocolForProxy:@protocol(ServerProtocol)];

		printf("new thread is %x\n", [proxy2 doWork]);
	}
	exit(0);
}
	